package com.example.redis.frequency;

import java.util.LinkedList;

public class PriorityQueue {

    public PriorityQueue() {
    }

    public PriorityQueue(Integer highSize, Integer lowSize) {
        this.highSize = highSize;
        this.lowSize = lowSize;
        highList = new LinkedList<>();
        lowList = new LinkedList<>();
    }

    /**
     * 添加
     *
     * @param priority
     * @param t
     * @throws IllegalStateException
     */
    public void add(Priority priority, Long t) throws IllegalStateException {
        boolean addResult = tryAdd(priority, t);
        if (!addResult) {
            if (priority == Priority.LOW) { // 低优先队列添加失败则直接失败
                StringBuilder msg = new StringBuilder();
                msg.append("lowSize:").append(lowSize).append(",currentSize:").append(lowList.size());
                throw new IllegalStateException(msg.toString());
            } else { // 高优先队列添加失败时再额外尝试添加低优先队列
                addResult = tryAddLow(t);
                if (!addResult) {
                    StringBuilder msg = new StringBuilder();
                    msg.append("highSize:").append(highSize).append(",currentSize:").append(highList.size());
                    msg.append("lowSize:").append(lowSize).append(",currentSize:").append(lowList.size());
                    throw new IllegalStateException(msg.toString());
                }
            }
        }
    }

    /**
     * 查看队列第一个元素
     *
     * @param priority
     * @return
     */
    public Long peek(Priority priority) {
        if (priority == Priority.LOW) {
            if (lowList.size() == 0) {
                return null;
            } else {
                return lowList.get(0);
            }
        } else {
            if (highList.size() == 0) {
                return null;
            } else {
                return highList.get(0);
            }
        }
    }

    /**
     * 取出队列第一个元素并将之从队列中删掉
     *
     * @param priority
     * @return
     */
    public Long poll(Priority priority) {
        Long result = null;
        if (priority == Priority.LOW) {
            if (lowList.size() != 0) {
                result = lowList.get(0);
                lowList.remove(0);
            }
        } else {
            if (highList.size() != 0) {
                result = highList.get(0);
                highList.remove(0);
            }
        }
        return result;
    }

    private Integer highSize;  //最新配置的高优先阀值
    private Integer lowSize;  //最新配置的低优先阀值
    private LinkedList<Long> highList; //真实的高优先级队列长度
    private LinkedList<Long> lowList; //真实的低优先级队列长度

    private boolean tryAdd(Priority priority, Long t) {
        if (priority == Priority.LOW) {
            return tryAddLow(t);
        } else {
            return tryAddHigh(t);
        }
    }

    private boolean tryAddLow(Long t) {
        if (lowList.size() < lowSize) {
            lowList.add(t);
            return true;
        }
        return false;
    }

    private boolean tryAddHigh(Long t) {
        if (highList.size() < highSize) {
            highList.add(t);
            return true;
        }
        return false;
    }

    public Integer getHighSize() {
        return highSize;
    }

    public void setHighSize(Integer highSize) {
        this.highSize = highSize;
    }

    public Integer getLowSize() {
        return lowSize;
    }

    public void setLowSize(Integer lowSize) {
        this.lowSize = lowSize;
    }

    public LinkedList<Long> getHighList() {
        return highList;
    }

    public void setHighList(LinkedList<Long> highList) {
        this.highList = highList;
    }

    public LinkedList<Long> getLowList() {
        return lowList;
    }

    public void setLowList(LinkedList<Long> lowList) {
        this.lowList = lowList;
    }

}
